/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef jit_ICState_h#define jit_ICState_h#include"jit/JitOptions.h"namespacejs{namespacejit{// ICState stores information about a Baseline or Ion IC.classICState{public:// When we attach the maximum number of stubs, we discard all stubs and// transition the IC to Megamorphic to attach stubs that are more generic// (handle more cases). If we again attach the maximum number of stubs, we// transition to Generic and (depending on the IC) will either attach a// single stub that handles everything or stop attaching new stubs.//// We also transition to Generic when we repeatedly fail to attach a stub,// to avoid wasting time trying.enumclassMode:uint8_t{Specialized=0,Megamorphic,Generic};private:Modemode_;// Number of optimized stubs currently attached to this IC.uint8_tnumOptimizedStubs_;// Number of times we failed to attach a stub.uint8_tnumFailures_;// This is only used for shared Baseline ICs and stored here to save space.boolinvalid_:1;staticconstsize_tMaxOptimizedStubs=6;voidtransition(Modemode){MOZ_ASSERT(mode>mode_);mode_=mode;numFailures_=0;}MOZ_ALWAYS_INLINEsize_tmaxFailures()const{// Allow more failures if we attached stubs.static_assert(MaxOptimizedStubs==6,"numFailures_/maxFailures should fit in uint8_t");size_tres=5+size_t(40)*numOptimizedStubs_;MOZ_ASSERT(res<=UINT8_MAX,"numFailures_ should not overflow");returnres;}public:ICState():invalid_(false){reset();}Modemode()const{returnmode_;}size_tnumOptimizedStubs()const{returnnumOptimizedStubs_;}MOZ_ALWAYS_INLINEboolcanAttachStub()const{MOZ_ASSERT(numOptimizedStubs_<=MaxOptimizedStubs);if(mode_==Mode::Generic||JitOptions.disableCacheIR)returnfalse;returntrue;}boolinvalid()const{returninvalid_;}voidsetInvalid(){invalid_=true;}// If this returns true, we transitioned to a new mode and the caller// should discard all stubs.MOZ_MUST_USEMOZ_ALWAYS_INLINEboolmaybeTransition(){MOZ_ASSERT(numOptimizedStubs_<=MaxOptimizedStubs);if(mode_==Mode::Generic)returnfalse;if(numOptimizedStubs_<MaxOptimizedStubs&&numFailures_<maxFailures())returnfalse;if(numFailures_==maxFailures()||mode_==Mode::Megamorphic){transition(Mode::Generic);returntrue;}MOZ_ASSERT(mode_==Mode::Specialized);transition(Mode::Megamorphic);returntrue;}voidreset(){mode_=Mode::Specialized;numOptimizedStubs_=0;numFailures_=0;}voidtrackAttached(){// We'd like to assert numOptimizedStubs_ < MaxOptimizedStubs, but// since this code is also used for non-CacheIR Baseline stubs, assert// < 16 for now. Note that we do have the stronger assert in other// methods, because they are only used by CacheIR ICs.MOZ_ASSERT(numOptimizedStubs_<16);numOptimizedStubs_++;numFailures_=0;}voidtrackNotAttached(){// Note: we can't assert numFailures_ < maxFailures() because// maxFailures() depends on numOptimizedStubs_ and it's possible a// GC discarded stubs before we got here.numFailures_++;MOZ_ASSERT(numFailures_>0,"numFailures_ should not overflow");}voidtrackUnlinkedStub(){MOZ_ASSERT(numOptimizedStubs_>0);numOptimizedStubs_--;}voidtrackUnlinkedAllStubs(){numOptimizedStubs_=0;}};}// namespace jit}// namespace js#endif /* jit_ICState_h */